<?php


namespace App\Service\Store;


use App\Constants\Express;
use App\Constants\Order;
use App\Dao\ExpressDao;
use App\Dao\LogisticDao;
use App\Dao\OrderDao;
use App\Dao\OrderItemDao;
use App\Dao\UserDao;
use App\Exception\CustomException;
use App\Kernel\Express\KdBird;
use App\Service\Service;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

/**
 * 订单服务
 * @author 陈奕文
 * @package App\Service\Store
 */
class OrderService extends Service
{

    /**
     * 订单Dao
     * @Inject()
     * @var OrderDao
     */
    public $dao;

    /**
     * 用户Dao
     * @Inject()
     * @var UserDao
     */
    public $user_dao;

    /**
     * 订单明细表
     * @Inject()
     * @var OrderItemDao
     */
    public $order_items_dao;

    /**
     * 物流Dao
     * @Inject()
     * @var LogisticDao
     */
    public $logistics_dao;


    /**
     * 快递Dao
     * @Inject()
     * @var ExpressDao
     */
    public $express_dao;

    /**
     * 快递鸟
     * @Inject()
     * @var KdBird
     */
    public $kd_bird;

    /**
     * 获得订单列表
     * @param array $params
     * @return mixed
     */
    public function getOrderList(array $params)
    {
        $map = [];
        isset($params['start_time']) && !isset($params['end_time'])  && !empty($params['start_time']) && $map['created_at'] = ['>=', strtotime($params['start_time'])]; // 下单开始时间
        isset($params['end_time']) &&  !isset($params['start_time'])  && !empty($params['end_time']) && $map['created_at'] = ['<=', strtotime($params['end_time'])]; // 下单结束时间

        isset($params['end_time']) &&  isset($params['start_time']) &&
        !empty($params['end_time']) && !empty($params['start_time']) &&
        $map['between_field'] = ['created_at' =>[strtotime($params['start_time']), strtotime($params['end_time'])]]; // 有下单开始和结束时间

        isset($params['user_id']) && !empty($params['user_id']) && $map['user_id'] = ['like', "%{$params['user_id']}%"]; // 用户ID
        isset($params['order_no']) && !empty($params['order_no']) && $map['order_no'] = ['like', "%{$params['order_no']}%"]; // 订单编号

        isset($params['status']) && $map['status'] = (int)$params['status']; // 订单状态/0=待支付/1=已支付(待发货)/2=已发货(待收货)/3=已完成/4=退款中/5=已退款/6=取消订单/7=已关闭


        // 姓名  手机号
        if ( (isset($params['name']) && !empty($params['name'])) || (isset($params['phone']) && !empty($params['phone']) ) ) {
            $user_map = [];
            isset($params['name']) && !empty($params['name']) && $user_map['name'] = ['like', "%{$params['name']}%"]; // 姓名
            isset($params['phone']) && !empty($params['phone']) && $user_map['phone'] = ['like', "%{$params['phone']}%"]; // 手机号
            $select = ['id', 'name', 'phone'];
            $users = $this->user_dao->getUsersByMap($user_map, null, $select)->toArray();
            if (!empty($users)) {
                $ids = array_column($users, 'id');
                $map['user_id'] = ['in', $ids]; // 用户ID
            } else { // 未查到用户
                $map['user_id'] = ['in', $users];
                // 分页
                $page_size = 20;

                $sort = 'created_at desc';
                $select = ['id', 'phone', 'name'];
                $user_cash_list = $this->dao->getOrdersByMapSelect($map, $sort, $select, $page_size)->toArray();
                return $user_cash_list;
            }
        }

        // 分页
        $page_size = 20;

        $sort = 'created_at desc';
        $select = ['id', 'user_id', 'order_no', 'total_price', 'price', 'status', 'created_at', 'integral'];

        $order_list = $this->dao->getOrdersByMapSelect($map, $sort, $select, $page_size)->toArray();

        $order_list['data'] = $this->joinData($order_list['data']);

        return $order_list;

    }

    /**
     * 数据拼接
     * @param array $order_list
     * @return array
     */
    public function joinData(array $order_list)
    {
        $user_ids = array_unique(array_column($order_list, 'user_id'));
        $name_phones = $this->user_dao->getUsersByIdsNotGroup($user_ids, ['id', 'name', 'phone']);

        $names = $name_phones->pluck('name', 'id');
        $phones = $name_phones->pluck('phone', 'id');
        foreach ($order_list as &$item) {
            $item['name'] = $names[$item['user_id']]??""; // 用户名
            $item['phone'] = $phones[$item['user_id']]??""; // 账号
            $item['status_text'] = Order::STATUS_LIST[$item['status']]; // 状态名称
            $item['create_time'] = date('Y.m.d H:i:s',(int)$item['created_at']);
        }
        return $order_list;
    }

    /**
     * 获得单个商品详情
     * @param int $id
     * @return mixed
     */
    public function getDetailById(int $id)
    {
        $order = $this->dao->getFirstOrder($id);
        empty($order) && $this->error('ORDER.NOT_EXIT');
        $order = $order->toArray();

        $order['pay_way'] = Order::PAY_WAY[$order['pay_type']]??""; // 支付方式名称
        $order['status_text'] = Order::STATUS_LIST[$order['status']]??""; // 订单状态名称
        $order['create_time'] = date("Y-m-d H:i:s", (int)$order['created_at']); // 下单时间
        return $order;
    }

    /**
     * 该订单初次发货并订阅物流信息给用户
     * @param array $params
     */
    public function deliver(array $params)
    {
//        !isset($params['id']) && $this->error("请传ID");

        $order = $this->dao->getFirstOrder((int)$params['id']);
        !$order && $this->error("ORDER.NOT_EXIT"); // 检测订单存在
        $map = [];
        $map['order_no'] = $order['order_no'];
        $express_name = $order->express_name;
        isset($params['express_name']) && !empty($params['express_name']) && $express_name = $params['express_name']; // 收货人姓名
        $map['name'] = $express_name;

        $express_phone = $order->express_phone;
        isset($params['express_phone']) && !empty($params['express_phone']) && $express_phone = $params['express_phone']; // 收货人手机
        $map['phone'] = $express_phone;

        $express_address = $order->express_address;
        isset($params['express_address']) && !empty($params['express_address']) && $express_address = $params['express_address']; // 收货人地址
        $map['address'] = $express_address;

        $map['pay_type'] = 1;
        isset($params['pay_type']) && !empty($params['pay_type']) && $map['pay_type'] = $params['pay_type']; // 运费支付方式

        $map['province'] = $params['province']; // 收件人省
        $map['city'] = $params['city']; // 收件人市
        $map['district'] = $params['district']; // 收件人区
        $map['sender_name'] = $params['sender_name']; // 发件人姓名
        $map['sender_phone'] = $params['sender_phone']; // 发件人手机号
        $map['sender_province'] = $params['sender_province']; // 发件人省
        $map['sender_city'] = $params['sender_city']; // 发件人市
        $map['sender_district'] = $params['sender_district']; // 发件人区
        $map['sender_addr'] = $params['sender_addr']; // 发件人地址


        $order['pay_time'] == 0 && $this->error("该订单还未支付"); // 支付时间

//        $order['ship_time'] > 0 && $this->error("该订单已是发货状态"); // 发货时间

//        $this->logistics_dao->logisticCount($order['order_no']) > 0 && $this->error("该订单已是发货状态"); // 物流数量

        $order['complete_time'] > 0 && $this->error('该订单已是收货状态'); // 收获时间

        $order['refund_time'] > 0 && $this->error('该订单已是退款状态'); // 退款时间

        $order['status'] != 1 && $this->error('该订单状态异常');

        // 验证物流公司是否存在
        $abbr_names = $this->express_dao->getAllExpress()->pluck('company_name', 'company_abbr')->toArray();

        !in_array($params['company_abbr'], array_keys($abbr_names)) && $this->error("不在可选择的快递公司里面");

        $map['zip_code'] = $order->express_zip_code;
        isset($params['express_zip_code']) && !empty($params['express_zip_code']) && $map['zip_code'] = $params['express_zip_code']; // 收货邮政编码

        $map['sender_zip_code'] = '';
        isset($params['sender_zip_code']) && !empty($params['sender_zip_code']) && $map['sender_zip_code'] = $params['sender_zip_code']; // 发货邮政编码


        if(in_array($params['company_abbr'], Express::CODE_REQUIRED_ZIP) ) { // 判断哪些需要邮政编码

            if (empty($map['zip_code'])) {
                $this->error($abbr_names[$params['company_abbr']]."需要收件的邮编号");
            }

            if ( empty($map['sender_zip_code']) ) {
                $this->error($abbr_names[$params['company_abbr']]."需要发件的邮编号");
            }
        }
        $map['custom_name'] = '';
        isset($params['custom_name']) && !empty($params['custom_name']) && $map['custom_name'] = $params['custom_name']; // 客户名称

        if (in_array($params['company_abbr'], Express::CODE_NEED_CUSTOM_NAME)) { //  哪些快递编号需要客户名称
           empty($map['custom_name']) && $this->error($abbr_names[$params['company_abbr']]."需要客户名称,请按规则来填写");

        }

        $map['number'] = $params['number']; // 物流单号

        $map['company_name'] = $abbr_names[$params['company_abbr']]; // 物流公司名
        $map['company_abbr'] = $params['company_abbr']; // 物流公司编号
        $map['current_detail'] = []; // 当前物流详情
        $map['status'] = 0; // // 当前物流状态

        $logistic = $this->logistics_dao->getLogisticByOrderNo($order['order_no']);

        $logistic && $this->error("物流信息已经存在");

        Db::beginTransaction();
        try {
            $create_logistics = $this->logistics_dao->create($map)->first();
            if(!$create_logistics)  throw new CustomException("物流信息保存失败");
            $current_logistic = $this->logistics_dao->getLogisticByNumber($map['number']);
            $order->ship_time = time(); // 发货时间
            $order->status = 2; // 待发货状态
            if (!$order->save()) throw new CustomException("物流信息保存成功，订单状态更新失败");

            $response = $this->sendDataSubscribe($map);
            if (!$response['Success']) {
                $this->logger('express')->error("订阅失败".json_encode($map));
                $current_logistic->subscribe_reason = $response['Reason']??"物流轨迹订阅失败。时间：".date("Y-m-d H:i:s");
                $current_logistic->save();
            } else {
                $current_logistic->is_subscribe = 1; // 订阅成功
                $current_logistic->subscribe_reason = $response['Reason']??"物流轨迹订阅成功。时间：".date("Y-m-d H:i:s");
                $current_logistic->save();
            }

            Db::commit();
        }catch (CustomException $e) {
            Db::rollBack();
            $this->error($e->getMessage());
        } catch (\Exception $e) {
            Db::rollBack();
            $this->error($e->getMessage());
        }


    }

    /**
     * 修改物流信息
     * @param array $params
     */
    public function polishInfo(array $params)
    {
        $logistic = $this->logistics_dao->getLogisticByOrderNo($params['order_no']);
        !$logistic && $this->error("该订单的物流不存在"); // 检测订单存在

        isset($params['express_name']) && !empty($params['express_name']) && $logistic->name = $params['express_name']; // 收货人姓名

        isset($params['express_phone']) && !empty($params['express_phone']) && $logistic->phone = $params['express_phone']; // 收货人手机

        isset($params['express_address']) && !empty($params['express_address']) && $logistic->address = $params['express_address']; // 收货人地址

        isset($params['express_zip_code']) && !empty($params['express_zip_code']) && $logistic->zip_code = $params['express_zip_code']; // 收货邮政编码

        isset($params['pay_type']) && !empty($params['pay_type']) && $logistic->pay_type = $params['pay_type']; // 运费支付方式

        isset($params['sender_zip_code']) && !empty($params['sender_zip_code']) && $logistic->sender_zip_code = $params['sender_zip_code']; // 发货邮政编码

        $changeNumber = false; // 是否改变了快递单号
        if (isset($params['number']) && !empty($params['number']) && $logistic->number != $params['number']) {
            $changeNumber = true;
        }

        isset($params['number']) && !empty($params['number']) && $logistic->number = $params['number']; // 物流单号

        isset($params['custom_name']) && !empty($params['custom_name']) && $logistic->custom_name = $params['custom_name']; // 客户名

        $logistic->province = $params['province']; // 收件人省
        $logistic->city = $params['city']; // 收件人市
        $logistic->district = $params['district']; // 收件人区
        $logistic->sender_name = $params['sender_name']; // 发件人姓名
        $logistic->sender_phone = $params['sender_phone']; // 发件人手机号
        $logistic->sender_province = $params['sender_province']; // 发件人省
        $logistic->sender_city = $params['sender_city']; // 发件人市
        $logistic->sender_district = $params['sender_district']; // 发件人区
        $logistic->sender_addr = $params['sender_addr']; // 发件人地址

        // 验证物流公司是否存在
        $abbr_names = $this->express_dao->getAllExpress()->pluck('company_name', 'company_abbr')->toArray();

        !in_array($params['company_abbr'], array_keys($abbr_names)) && $this->error("不在可选择的快递公司里面");

        $changeAbbr = false; // 是否改变了物流公司编号
        if(isset($params['company_abbr']) && !empty($params['company_abbr']) ) {
            $logistic->company_abbr != $params['company_abbr'] && $changeAbbr = true;

            $logistic->company_abbr = $params['company_abbr']; // 物流编号
            $logistic->company_name = $abbr_names[$params['company_abbr']]; // 物流公司名
        }

        $logistic->save();
        // 重新订阅的情况
        if (isset($params['subscribe']) && $params['subscribe'] == 1) {
            $new_logistic = $this->logistics_dao->getLogisticByOrderNo($params['order_no']);
            $new_logistic_data = $new_logistic->toArray();
            $response = $this->sendDataSubscribe($new_logistic_data);
            if ($response['Success']) {
                $new_logistic->is_subscribe = 1; // 订阅
                $new_logistic->subscribe_reason = $response['Reason']??"重新订阅成功。时间：".date("Y-m-d H:i:s");
                $new_logistic->save();
            } else {
                if ($changeNumber || $changeAbbr) { // 修改过了的快递单号或者物流公司编号
                    $new_logistic->is_subscribe = 0;
                }
                $new_logistic->subscribe_reason = $response['Reason']??"重新订阅失败。时间：".date("Y-m-d H:i:s");
                $new_logistic->save();
            }
        }


    }



    /**
     * 发送需要订阅的数据
     * @param array $data
     * @return mixed
     */
    public function sendDataSubscribe(array $data)
    {
        $send = [
            'ShipperCode' => $data['company_abbr'], // 快递编码
            'LogisticCode' => $data['number'], // 快递单号
            'PayType' => $data['pay_type'], // 运费支付方式
            'CustomerName' => $data['custom_name'], // 客户名称
            'Receiver' => [
                'Name' => $data['name'],
                'Mobile' => $data['phone'],
                'ProvinceName' => $data['province'],
                'CityName' => $data['city'],
                'ExpAreaName' => $data['district'],
                'Address' => $data['address'],
                'PostCode' => $data['zip_code'], // 邮编
            ],
            'Sender' => [
                'Name' => $data['sender_name'],
                'Mobile' => $data['sender_phone'],
                'ProvinceName' => $data['sender_province'],
                'CityName' => $data['sender_city'],
                'ExpAreaName' => $data['sender_district'],
                'Address' => $data['sender_addr'],
                'PostCode' => $data['sender_zip_code'],
            ],
        ];
        $response = $this->kd_bird->orderTracesSubByJson($send, config('express.request_type'));
        return $response;
    }
    
}